package com.fingard.dsp.bank.directbank.allinpay02;

import com.alibaba.fastjson.JSONObject;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IContract;
import com.fingard.dsp.bank.reqrespobj.contract.*;
import com.fingard.dsp.bank.reqrespobj.contract.detail.RetAtsContractDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import msoa.org.apache.commons.codec.binary.Base64;

import java.util.Date;
import java.util.HashMap;

/**
 * 通联商业委托签约/协议签约
 * <p>
 * 参考接口文档：通联通标准签约接口规范V1.0-商业委托扣款.docx
 *
 * @author fanghh
 * @date 2018/7/27
 */
public class AllInPay02Contract extends AllInPay02Base implements IContract {
    @Override
    public RetAtsContract contract(ReqContract p_req) throws Exception {
        RetAtsContract retAts = new RetAtsContract(p_req.reqHeader);
        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        tmpRetDetail.reqSeqID = p_req.contractDetail.askNumber;

        if ("9108JFBAgrm".equals(p_req.reqHeader.commandCode) || "9108JFBAuth".equals(p_req.reqHeader.commandCode) || "9108JFBCntr".equals(p_req.reqHeader.commandCode)) {
            tmpRetDetail = contractBy9108JFB(p_req);
        } else if ("9108Agrm".equals(p_req.reqHeader.commandCode)) {
            tmpRetDetail = contractBy9108Agrm(p_req);
        } else if ("9108Auth".equals(p_req.reqHeader.commandCode)) {
            tmpRetDetail = contractBy9108Auth(p_req);
        } else {
            tmpRetDetail.respInfo = "不支持的指令类型：" + p_req.reqHeader.transType + "-" + p_req.reqHeader.commandCode;
        }

        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    @Override
    public RetAtsContract upContract(ReqContract p_req) throws Exception {
        return null;
    }

    /**
     * 通联协议签约申请+签约确认
     *
     * @param p_req
     * @return
     * @throws Exception
     */
    public RetAtsContractDetail contractBy9108Agrm(ReqContract p_req) throws Exception {
        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        tmpRetDetail.reqSeqID = p_req.contractDetail.askNumber;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.contractDetail.recAct, "contract");
            if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath)
                    || !FileHelper.existFile(actItem.oppCertFilePath)) {
                tmpRetDetail.respCode = "-1";
                if (actItem == null) {
                    tmpRetDetail.respInfo = "未找到账号[" + p_req.contractDetail.recAct + "]商户配置信息!";
                } else {
                    tmpRetDetail.respInfo = "账号[" + p_req.contractDetail.recAct + "]证书文件不存在";
                }
                return tmpRetDetail;
            }

            XmlTextWriter xmlWriter = new XmlTextWriter();
            if ("01".equals(p_req.contractDetail.step)) {
                AllInPay02Header header = new AllInPay02Header();
                header.TRX_CODE = "310001";
                header.REQ_SN = p_req.contractDetail.askNumber;

                writeContractCommonHeader(xmlWriter, header, actItem);

                xmlWriter.writeStartElement("FAGRA");
                xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);

                String[] findValues = new String[2];
                findValues[0] = p_req.contractDetail.payBankCode;
                findValues[1] = "";

                if (getBankConfig().getValueAsBool("BANK_CODE_ISEMPTY")) {
                    xmlWriter.writeElementString("BANK_CODE", "");
                } else {
                    HashMap<String, String> BANK_CODE = this.getBankConfig().getMapAdvanceValues("BankCodeMapping",
                            new String[]{"ATSBankCode", "ATSAreaName"}, new String[]{"value"}, findValues);
                    if (BANK_CODE != null && BANK_CODE.size() > 0 && BANK_CODE.containsKey("value")) {
                        xmlWriter.writeElementString("BANK_CODE", BANK_CODE.get("value"));
                    } else {
                        xmlWriter.writeElementString("BANK_CODE", findValues[0]);
                    }
                }

                String cardType = p_req.contractDetail.cardType;
                if ("3".equals(cardType) || "4".equals(cardType)) {
                    cardType = "02";// 信用卡
                } else {
                    cardType = "00";// 借记卡(默认)
                }
                xmlWriter.writeElementString("ACCOUNT_TYPE", cardType);
                xmlWriter.writeElementString("ACCOUNT_NO", p_req.contractDetail.payAct);
                xmlWriter.writeElementString("ACCOUNT_NAME", p_req.contractDetail.payName);

                String isPrivate = p_req.contractDetail.isPrivate;
                if ("1".equals(isPrivate)) {
                    isPrivate = "0";
                } else {
                    isPrivate = "1";
                }
                xmlWriter.writeElementString("ACCOUNT_PROP", isPrivate);
                xmlWriter.writeElementString("ID_TYPE", convertCertTypeToBank(p_req.contractDetail.certType));
                xmlWriter.writeElementString("ID", p_req.contractDetail.certNum);
                xmlWriter.writeElementString("TEL", p_req.contractDetail.cellPhone);
                xmlWriter.writeElementString("CVV2", p_req.contractDetail.cvv2);
                xmlWriter.writeElementString("VALIDDATE", p_req.contractDetail.expiredDate);
                xmlWriter.writeElementString("MERREM", "");
                xmlWriter.writeElementString("REMARK", "");
                xmlWriter.writeEndDocument();
            } else if ("02".equals(p_req.contractDetail.step)) {
                AllInPay02Header header = new AllInPay02Header();
                header.TRX_CODE = "310002";
                header.REQ_SN = p_req.reqHeader.transSeqID;

                writeContractCommonHeader(xmlWriter, header, actItem);

                xmlWriter.writeStartElement("FAGRC");
                xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                xmlWriter.writeElementString("SRCREQSN", p_req.contractDetail.askNumber);
                xmlWriter.writeElementString("VERCODE", p_req.contractDetail.smsCode);
                xmlWriter.writeEndDocument();
            } else {
                tmpRetDetail.respCode = "0";
                tmpRetDetail.respInfo = "未能识别的step：" + p_req.contractDetail.step;
                tmpRetDetail.signState = ContractState.FAIL;
                return tmpRetDetail;
            }

            String[] tmpStrRet = sendContractToBank(xmlWriter.toXmlString(), actItem);

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    tmpRetDetail.respCode = "0";
                    tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");

                    if ("0000".equals(tmpBkReader.getFirstText("/AIPG/INFO/RET_CODE"))) {
                        String tmpRespCode = "";
                        if ("01".equals(p_req.contractDetail.step)) {
                            tmpRespCode = tmpBkReader.getFirstText("/AIPG/FAGRARET/RET_CODE");
                            if (!"0000".equals(tmpRespCode)) {
                                tmpRetDetail.respCode = "-1";
                                tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/FAGRARET/ERR_MSG");
                            }
                            tmpRetDetail.signConfirmType = this.getBankConfig().getMapValueByKey("signConfirmMapping", p_req.contractDetail.payBankCode);
                        } else {
                            tmpRespCode = tmpBkReader.getFirstText("/AIPG/FAGRCRET/RET_CODE");
                            if ("0000".equals(tmpRespCode)) {
                                tmpRetDetail.signState = ContractState.SUCCESS;
                            } else {
                                tmpRetDetail.signState = ContractState.FAIL;
                            }
                            tmpRetDetail.authCode = tmpBkReader.getFirstText("/AIPG/FAGRCRET/AGRMNO");
                            String tmpRespInfo = tmpBkReader.getFirstText("/AIPG/FAGRCRET/ERR_MSG");
                            if (StringHelper.hasAnyChar(tmpRespInfo)) {
                                tmpRetDetail.respInfo = tmpRespInfo;
                            }
                        }
                        tmpRetDetail.unifiedCode = getBankConfig().getMapValueByKey("contractMapping", tmpRespCode);
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return tmpRetDetail;
    }

    /**
     * 通联商业委托签约申请+签约确认
     *
     * @param p_req
     * @return
     * @throws Exception
     */
    public RetAtsContractDetail contractBy9108Auth(ReqContract p_req) throws Exception {
        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        tmpRetDetail.reqSeqID = p_req.contractDetail.askNumber;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.contractDetail.recAct, "contract");
            if (actItem != null) {
                XmlTextWriter xmlWriter = new XmlTextWriter();
                if ("01".equals(p_req.contractDetail.step)) {
                    AllInPay02Header header = new AllInPay02Header();
                    header.TRX_CODE = "340001";
                    header.REQ_SN = p_req.contractDetail.askNumber;

                    writeAgrmCommonHeader(xmlWriter, header, actItem);

                    xmlWriter.writeStartElement("AGRINFO");
                    xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                    xmlWriter.writeElementString("SUBMIT_TIME", Format.DateTime14Format.format(new Date()));
                    boolean limit = getBankConfig().getValueAsBool("useBankMapping");
                    if (limit) {
                        xmlWriter.writeElementString("SIGN_MODE", getBankConfig().getMapValueByKey("signModeBankMapping", p_req.contractDetail.payBankCode));
                    } else {
                        xmlWriter.writeElementString("SIGN_MODE", "0");
                    }
                    WriteBankLogLn("useBankMapping为：" + limit + "，payBankCode为：" + p_req.contractDetail.payBankCode + ",signModeBankMapping为：" + getBankConfig().getMapValueByKey("signModeBankMapping", p_req.contractDetail.payBankCode));
                    xmlWriter.writeElementString("BUSINESS_CODE", "10600");// todo

                    String[] findValues = new String[2];
                    findValues[0] = p_req.contractDetail.payBankCode;
                    findValues[1] = "";
                    HashMap<String, String> BANK_CODE = this.getBankConfig().getMapAdvanceValues("BankCodeMapping",
                            new String[]{"ATSBankCode", "ATSAreaName"}, new String[]{"value"}, findValues);
                    if (BANK_CODE != null && BANK_CODE.size() > 0 && BANK_CODE.containsKey("value")) {
                        xmlWriter.writeElementString("BANK_CODE", BANK_CODE.get("value"));
                    } else {
                        xmlWriter.writeElementString("BANK_CODE", findValues[0]);
                    }
//					xmlWriter.writeElementString("BANK_CODE", "");// todo

                    String cardType = p_req.contractDetail.cardType;
                    if ("3".equals(cardType) || "4".equals(cardType)) {
                        cardType = "02";// 信用卡
                    } else {
                        cardType = "00";// 借记卡(默认)
                    }
                    xmlWriter.writeElementString("ACCOUNT_TYPE", cardType);
                    xmlWriter.writeElementString("ACCOUNT_NO", p_req.contractDetail.payAct);
                    xmlWriter.writeElementString("ACCOUNT_NAME", p_req.contractDetail.payName);

                    String isPrivate = p_req.contractDetail.isPrivate;
                    if ("1".equals(isPrivate)) {
                        isPrivate = "0";
                    } else {
                        isPrivate = "1";
                    }
                    xmlWriter.writeElementString("ACCOUNT_PROP", isPrivate);
                    xmlWriter.writeElementString("ID_TYPE", convertCertTypeToBank(p_req.contractDetail.certType));
                    xmlWriter.writeElementString("ID", p_req.contractDetail.certNum);
                    xmlWriter.writeElementString("TEL", p_req.contractDetail.cellPhone);
                    xmlWriter.writeElementString("LEGAL", p_req.contractDetail.legalName);
                    xmlWriter.writeElementString("LEGALIDTYPE",
                            convertCertTypeToBank(p_req.contractDetail.legalCertType));
                    xmlWriter.writeElementString("LEGALIDNO", p_req.contractDetail.legalCertNum);
                    String deadLine = p_req.contractDetail.deadLine;
                    if (StringHelper.isNullOrEmpty(deadLine)) {
                        deadLine = getBankConfig().getMapValueByKey("contractKeyMapping", "deadLine");
                        if (StringHelper.isNullOrEmpty(deadLine)) {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = "缺失配置节点'deadLine'或值为空!";
                            return tmpRetDetail;
                        }
                    }
                    xmlWriter.writeElementString("EXPIRED", deadLine);

                    String singleLimit = p_req.contractDetail.singleLimit;
                    if (StringHelper.isNullOrEmpty(singleLimit)) {
                        if (getBankConfig().getValueAsBool("singleLimitCut")) {
                            singleLimit = getBankConfig().getMapValueByKey("singleLimitMapping", p_req.contractDetail.payBankCode);
                        } else {
                            singleLimit = getBankConfig().getMapValueByKey("contractKeyMapping", "singleLimit");
                        }
                        if (StringHelper.isNullOrEmpty(singleLimit)) {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = "缺失配置节点'singleLimit'或值为空!";
                            return tmpRetDetail;
                        }
                    }
                    xmlWriter.writeElementString("SINGLEMAXAMT", StringHelper.amountMultiply100(singleLimit));

                    String periodLimit = p_req.contractDetail.periodLimit;
                    if (StringHelper.isNullOrEmpty(periodLimit)) {
                        periodLimit = getBankConfig().getMapValueByKey("contractKeyMapping", "periodLimit");
                        if (StringHelper.isNullOrEmpty(periodLimit)) {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = "缺失配置节点'periodLimit'或值为空!";
                            return tmpRetDetail;
                        }
                    }
                    if ("1".equals(periodLimit)) {
                        periodLimit = "D";
                    } else if ("2".equals(periodLimit)) {
                        periodLimit = "M";
                    } else {
                        periodLimit = "Y";
                    }
                    xmlWriter.writeElementString("PERIOD_UNIT", periodLimit);

                    String countLimit = p_req.contractDetail.countLimit;
                    if (StringHelper.isNullOrEmpty(countLimit)) {
                        countLimit = getBankConfig().getMapValueByKey("contractKeyMapping", "countLimit");
                        if (StringHelper.isNullOrEmpty(countLimit)) {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = "缺失配置节点'countLimit'或值为空!";
                            return tmpRetDetail;
                        }
                    }
                    xmlWriter.writeElementString("MAX_CNT_LIMIT", countLimit);
                    xmlWriter.writeElementString("MERREM", "");
                    xmlWriter.writeElementString("REMARK", "");
                    xmlWriter.writeEndDocument();
                } else if ("02".equals(p_req.contractDetail.step)) {
                    AllInPay02Header header = new AllInPay02Header();
                    header.TRX_CODE = "340002";
                    header.REQ_SN = p_req.reqHeader.transSeqID;

                    writeAgrmCommonHeader(xmlWriter, header, actItem);

                    xmlWriter.writeStartElement("AGRCFM");
                    xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                    xmlWriter.writeElementString("SRCREQSN", p_req.contractDetail.askNumber);
                    xmlWriter.writeElementString("VERCODE", p_req.contractDetail.smsCode);
                    xmlWriter.writeEndDocument();
                } else {
                    tmpRetDetail.respCode = "0";
                    tmpRetDetail.respInfo = "未能识别的step：" + p_req.contractDetail.step;
                    tmpRetDetail.signState = ContractState.FAIL;
                    return tmpRetDetail;
                }

                String[] tmpStrRet = sendContractToBank(xmlWriter.toXmlString(), actItem);

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");

                        if ("0000".equals(tmpBkReader.getFirstText("/AIPG/INFO/RET_CODE"))) {
                            String tmpRespCode = "";
                            if ("01".equals(p_req.contractDetail.step)) {
                                tmpRespCode = tmpBkReader.getFirstText("/AIPG/AGRRSP/RET_CODE");
                                if (!"0000".equals(tmpRespCode)) {
                                    tmpRetDetail.respCode = "-1";
                                    tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/AGRRSP/ERR_MSG");
                                }
                                tmpRetDetail.signConfirmType = this.getBankConfig().getMapValueByKey("signConfirmMapping", p_req.contractDetail.payBankCode);
                                tmpRetDetail.signUrl = tmpBkReader.getFirstText("/AIPG/AGRRSP/URL");
                                if (StringHelper.hasAnyChar(tmpRetDetail.signUrl)) {
                                    String tmpdata = tmpBkReader.getFirstText("/AIPG/AGRRSP/DATA");
                                    if (!StringHelper.isNullOrEmpty(tmpdata)) {
                                        String data = new String(Base64.decodeBase64(tmpdata.getBytes("GBK")), "GBK");
                                        JSONObject jsonob = JSONObject.parseObject(data);
                                        tmpRetDetail.signUrl = tmpRetDetail.signUrl + "?version=" + jsonob.getString("version") + "&msgType=" + jsonob.getString("msgType") + "&sign=" + jsonob.getString("sign") + "&xml_msg=" + jsonob.getString("xml_msg");
                                    }
                                }
                            } else {
                                tmpRespCode = tmpBkReader.getFirstText("/AIPG/AGRCFMRSP/RET_CODE");
                                if ("0000".equals(tmpRespCode)) {
                                    tmpRetDetail.signState = ContractState.SUCCESS;
                                } else {
                                    tmpRetDetail.signState = ContractState.FAIL;
                                }
                                tmpRetDetail.authCode = tmpBkReader.getFirstText("/AIPG/AGRCFMRSP/AGRMNO");
                                String tmpRespInfo = tmpBkReader.getFirstText("/AIPG/AGRCFMRSP/ERR_MSG");
                                if (StringHelper.hasAnyChar(tmpRespInfo)) {
                                    tmpRetDetail.respInfo = tmpRespInfo;
                                }
                            }
                            tmpRetDetail.unifiedCode = getBankConfig().getMapValueByKey("contractMapping", tmpRespCode);
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "未找到账号[" + p_req.contractDetail.recAct + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return tmpRetDetail;
    }

    /**
     * 通联金服宝签约申请+签约确认
     *
     * @param p_req
     * @return
     * @throws Exception
     */
    public RetAtsContractDetail contractBy9108JFB(ReqContract p_req) throws Exception {
        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        tmpRetDetail.reqSeqID = p_req.contractDetail.askNumber;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.contractDetail.recAct, "contract");
            if (actItem != null) {
                XmlTextWriter xmlWriter = new XmlTextWriter();
                AllInPay02Header header = new AllInPay02Header();
                if ("01".equals(p_req.contractDetail.step)) {
                    header.TRX_CODE = "310001";
                    header.REQ_SN = p_req.contractDetail.askNumber;

                    writeJFBCommonHeader(xmlWriter, header, actItem);

                    xmlWriter.writeStartElement("BODY");
                    xmlWriter.writeStartElement("AGRINFO");
                    xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                    xmlWriter.writeElementString("SUBMIT_TIME", Format.DateTime17Format.format(new Date()));

                    String agrType = "0";
                    if ("9108JFBAgrm".equalsIgnoreCase(p_req.reqHeader.commandCode)) {
                        agrType = "0";
                    } else if ("9108JFBAuth".equalsIgnoreCase(p_req.reqHeader.commandCode)) {
                        agrType = "1";
                    } else if ("9108JFBCntr".equalsIgnoreCase(p_req.reqHeader.commandCode)) {
                        agrType = "2";
                    }
                    xmlWriter.writeElementString("AGR_TYPE", agrType);
                    xmlWriter.writeElementString("SIGN_MODE", getBankConfig().getMapValueByKey("signModeBankMapping", p_req.contractDetail.payBankCode));
                    String[] findValues = new String[2];
                    findValues[0] = p_req.contractDetail.payBankCode;
                    findValues[1] = "";
                    if (getBankConfig().getValueAsBool("BANK_CODE_ISEMPTY")) {
                        xmlWriter.writeElementString("BANK_CODE", "");
                    } else {
                        HashMap<String, String> BANK_CODE = this.getBankConfig().getMapAdvanceValues("BankCodeMapping",
                                new String[]{"ATSBankCode", "ATSAreaName"}, new String[]{"value"}, findValues);
                        if (BANK_CODE != null && BANK_CODE.size() > 0 && BANK_CODE.containsKey("value")) {
                            xmlWriter.writeElementString("BANK_CODE", BANK_CODE.get("value"));
                        } else {
                            xmlWriter.writeElementString("BANK_CODE", findValues[0]);
                        }
                    }
                    xmlWriter.writeElementString("ACCOUNT_NO", p_req.contractDetail.payAct);
                    xmlWriter.writeElementString("ACCOUNT_NAME", p_req.contractDetail.payName);
                    String cardType = p_req.contractDetail.cardType;
                    if ("3".equals(cardType) || "4".equals(cardType)) {
                        cardType = "02";// 信用卡
                    } else {
                        cardType = "00";// 借记卡(默认)
                    }
                    xmlWriter.writeElementString("ACCOUNT_TYPE", cardType);

                    String isPrivate = p_req.contractDetail.isPrivate;
                    if ("1".equals(isPrivate)) {
                        isPrivate = "0";
                    } else {
                        isPrivate = "1";
                    }
                    xmlWriter.writeElementString("ACCOUNT_PROP", isPrivate);
                    xmlWriter.writeElementString("ID_TYPE", convertCertTypeToBank(p_req.contractDetail.certType));
                    xmlWriter.writeElementString("ID", p_req.contractDetail.certNum);
                    xmlWriter.writeElementString("TEL", p_req.contractDetail.cellPhone);
                    xmlWriter.writeElementString("CVV2", p_req.contractDetail.cvv2);
                    xmlWriter.writeElementString("VALIDDATE", p_req.contractDetail.expiredDate);
                    xmlWriter.writeElementString("MERREM", "");
                    xmlWriter.writeElementString("REMARK", "");
                    xmlWriter.writeElementString("NOTIFYURL", actItem.notifyURL);
                    xmlWriter.writeEndDocument();
                } else if ("02".equals(p_req.contractDetail.step)) {
                    header.TRX_CODE = "310002";
                    header.REQ_SN = p_req.reqHeader.transSeqID;

                    writeJFBCommonHeader(xmlWriter, header, actItem);

                    xmlWriter.writeStartElement("BODY");
                    xmlWriter.writeStartElement("SIGNCFM_REQ");
                    xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                    xmlWriter.writeElementString("SRC_REQSN", p_req.contractDetail.askNumber);
                    xmlWriter.writeElementString("VERCODE", p_req.contractDetail.smsCode);
                    xmlWriter.writeEndDocument();
                } else {
                    tmpRetDetail.respCode = "0";
                    tmpRetDetail.respInfo = "未能识别的step：" + p_req.contractDetail.step;
                    tmpRetDetail.signState = ContractState.FAIL;
                    return tmpRetDetail;
                }

                String[] tmpStrRet = sendJFBToBank(xmlWriter.toXmlString(), actItem, header.REQ_SN);

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/HEAD/RET_MSG");
                        String tmpRespCode = tmpBkReader.getFirstText("/AIPG/HEAD/RET_CODE");
                        if (StringHelper.hasAnyChar(tmpRespCode)) {
                            if ("01".equals(p_req.contractDetail.step)) {
                                if ("0000".equals(tmpRespCode)) {
                                    String authCode = tmpBkReader.getFirstText("/AIPG/BODY/AGRRSP/TLAGRMNO");
                                    if(StringHelper.hasAnyChar(authCode)){
                                        tmpRespCode = "SC001";
                                        tmpRetDetail.authCode = authCode;
                                    }
                                    tmpRetDetail.signUrl = tmpBkReader.getFirstText("/AIPG/BODY/AGRRSP/URL");

                                } else {
                                    tmpRetDetail.respCode = "-1";
                                }
                            } else {
                                if ("0000".equals(tmpRespCode)) {
                                    tmpRetDetail.signState = ContractState.SUCCESS;
                                } else if ("4000".equals(tmpRespCode) || "2008".equals(tmpRespCode) || "2007".equals(tmpRespCode)) {
                                    tmpRetDetail.signState = ContractState.SIGNING;
                                } else {
                                    if (tmpRespCode.startsWith("3")) {
                                        tmpRetDetail.signState = ContractState.FAIL;
                                    }
                                }
                                tmpRetDetail.authCode = tmpBkReader.getFirstText("/AIPG/BODY/SIGNCFM_RSP/TLAGRMNO");
                            }
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/HEAD/RET_MSG");
                        }

                        tmpRetDetail.unifiedCode = getBankConfig().getMapValueByKey("contractMapping", tmpRespCode);
                        tmpRetDetail.signConfirmType = this.getBankConfig().getMapValueByKey("signConfirmMapping", p_req.contractDetail.payBankCode);
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "未找到账号[" + p_req.contractDetail.recAct + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return tmpRetDetail;
    }

    @Override
    public RetAtsContract qryContract(ReqContract p_reqQry) throws Exception {
        RetAtsContract retAts = new RetAtsContract(p_reqQry.reqHeader);

        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        tmpRetDetail.reqSeqID = p_reqQry.contractDetail.askNumber;

        if ("9108JFBAgrm".equals(p_reqQry.reqHeader.commandCode) || "9108JFBAuth".equals(p_reqQry.reqHeader.commandCode) || "9108JFBCntr".equals(p_reqQry.reqHeader.commandCode)) {
            tmpRetDetail = qryContractBy9108JFB(p_reqQry);
        } else if ("9108Auth".equals(p_reqQry.reqHeader.commandCode)) {
            tmpRetDetail = qryContractBy9108Auth(p_reqQry);
        } else if ("9108Agrm".equals(p_reqQry.reqHeader.commandCode)) {
            tmpRetDetail = qryContractBy9108Agrm(p_reqQry);
        } else {
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = "不支持的指令类型：" + p_reqQry.reqHeader.transType + "-" + p_reqQry.reqHeader.commandCode;
        }

        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    @Override
    public RetAtsQryBatContract qryBatContract(ReqQryBatContract p_reqQry) throws Exception {
        return null;
    }

    /**
     * 通联商业委托签约查询
     *
     * @param p_reqQry
     * @return
     * @throws Exception
     */
    public RetAtsContractDetail qryContractBy9108Auth(ReqContract p_reqQry) throws Exception {
        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        tmpRetDetail.reqSeqID = p_reqQry.contractDetail.askNumber;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQry.contractDetail.recAct, "contract");
            if (actItem != null) {
                AllInPay02Header bankHeader = new AllInPay02Header();
                bankHeader.REQ_SN = getQryTransID();
                bankHeader.TRX_CODE = "340009";

                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeAgrmCommonHeader(xmlWriter, bankHeader, actItem);

                xmlWriter.writeStartElement("QAGRINFO");
                xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                xmlWriter.writeElementString("AGRTYPE", "00");
                xmlWriter.writeElementString("QUERY_MODE", "3");
                xmlWriter.writeElementString("QUERY_SN", p_reqQry.contractDetail.askNumber);
                xmlWriter.writeElementString("ACCOUNT_NO", p_reqQry.contractDetail.payAct);
                xmlWriter.writeElementString("AGRMNO", "");
                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), actItem);

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");

                        String tmpRespCode = tmpBkReader.getFirstText("/AIPG/INFO/RET_CODE");
                        if ("0000".equals(tmpRespCode)) {
                            String tmpRespInfo = tmpBkReader.getFirstText("/AIPG/QAGRRSP/QAGRDETAIL/ERR_MSG");
                            if (StringHelper.hasAnyChar(tmpRespInfo)) {
                                tmpRetDetail.respInfo = tmpRespInfo;
                            }

                            String contractState = tmpBkReader.getFirstText("/AIPG/QAGRRSP/QAGRDETAIL/STATUS");
                            if ("2".equals(contractState)) {
                                contractState = ContractState.SUCCESS;
                            } else if ("1".equals(contractState)) {
                                contractState = ContractState.UNSIGNED;
                            }
                            tmpRetDetail.signState = contractState;

                            if (ContractState.SUCCESS.equals(tmpRetDetail.signState)) {
                                if (tmpBkReader.read("/AIPG/QAGRRSP/QAGRDETAIL")) {
                                    tmpRetDetail.authCode = tmpBkReader.readedXElement.getSingleText("AGRMNO");
                                    tmpRetDetail.payAct = tmpBkReader.readedXElement.getSingleText("ACCOUNT_NO");
                                    tmpRetDetail.deadLine = tmpBkReader.readedXElement.getSingleText("EXPIRED");
                                    String singleLimit = tmpBkReader.readedXElement.getSingleText("SINGLEMAXAMT");
                                    if (StringHelper.hasAnyChar(singleLimit)) {
                                        tmpRetDetail.singleLimit = StringHelper.amountDivide100(singleLimit);
                                    }
                                    String periodLimit = tmpBkReader.readedXElement.getSingleText("PERIOD_UNIT");
                                    if (StringHelper.hasAnyChar(periodLimit)) {
                                        if ("D".equals(periodLimit)) {
                                            periodLimit = "1";
                                        } else if ("M".equals(periodLimit)) {
                                            periodLimit = "2";
                                        } else {
                                            periodLimit = "3";
                                        }
                                        tmpRetDetail.periodLimit = periodLimit;
                                    }
                                    tmpRetDetail.countLimit = tmpBkReader.readedXElement.getSingleText("MAX_CNT_LIMIT");
                                }
                            }
                        } else if ("1002".equals(tmpRespCode)) {
                            tmpRetDetail.respCode = "0";
                            tmpRetDetail.signState = ContractState.UNSIGNED;
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");
                        }
                        tmpRetDetail.signConfirmType = this.getBankConfig().getMapValueByKey("signConfirmMapping", p_reqQry.contractDetail.payBankCode);
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "未找到账号:[" + p_reqQry.contractDetail.recAct + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return tmpRetDetail;
    }

    public RetAtsContractDetail qryContractBy9108Agrm(ReqContract p_reqQry) throws Exception {
        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQry.contractDetail.recAct, "contract");
            if (actItem != null) {
                AllInPay02Header bankHeader = new AllInPay02Header();
                bankHeader.REQ_SN = getQryTransID();
                bankHeader.TRX_CODE = "340009";

                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeAgrmCommonHeader(xmlWriter, bankHeader, actItem);

                xmlWriter.writeStartElement("QAGRINFO");
                xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                xmlWriter.writeElementString("AGRTYPE", "01");
                xmlWriter.writeElementString("QUERY_MODE", "3");
                xmlWriter.writeElementString("ACCOUNT_NO", p_reqQry.contractDetail.payAct);
                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), actItem);

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");

                        String tmpRespCode = tmpBkReader.getFirstText("/AIPG/INFO/RET_CODE");
                        if ("0000".equals(tmpRespCode)) {
                            String tmpRespInfo = tmpBkReader.getFirstText("/AIPG/QAGRRSP/QAGRDETAIL/ERR_MSG");
                            if (StringHelper.hasAnyChar(tmpRespInfo)) {
                                tmpRetDetail.respInfo = tmpRespInfo;
                            }

                            // 0待确认 1失败 2成功
                            String contractState = tmpBkReader.getFirstText("/AIPG/QAGRRSP/QAGRDETAIL/STATUS");
                            if ("2".equals(contractState)) {
                                contractState = ContractState.SUCCESS;
                            } else if ("1".equals(contractState)) {
                                contractState = ContractState.FAIL;
                            } else {
                                contractState = ContractState.SIGNING;
                            }
                            tmpRetDetail.signState = contractState;

                            if (ContractState.SUCCESS.equals(tmpRetDetail.signState)) {
                                if (tmpBkReader.read("/AIPG/QAGRRSP/QAGRDETAIL")) {
                                    tmpRetDetail.authCode = tmpBkReader.readedXElement.getSingleText("AGRMNO");
                                    tmpRetDetail.payAct = tmpBkReader.readedXElement.getSingleText("ACCOUNT_NO");
                                }
                            }
                        } else if ("1002".equals(tmpRespCode)) {
                            tmpRetDetail.respCode = "0";
                            tmpRetDetail.signState = ContractState.UNSIGNED;
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/INFO/ERR_MSG");
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "未找到账号:[" + p_reqQry.contractDetail.recAct + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }
        return tmpRetDetail;
    }

    public RetAtsContractDetail qryContractBy9108JFB(ReqContract p_reqQry) throws Exception {
        RetAtsContractDetail tmpRetDetail = new RetAtsContractDetail();
        tmpRetDetail.reqSeqID = p_reqQry.contractDetail.askNumber;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQry.contractDetail.recAct, "contract");
            if (actItem != null) {
                AllInPay02Header bankHeader = new AllInPay02Header();
                bankHeader.REQ_SN = getQryTransID();
                bankHeader.TRX_CODE = "340009";

                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeJFBCommonHeader(xmlWriter, bankHeader, actItem);

                xmlWriter.writeStartElement("BODY");
                xmlWriter.writeStartElement("QAGRINFO");
                String queryMode = getBankConfig().getValueAsString("queryMode");
                if (StringHelper.isNullOrEmpty(queryMode)) {
                    xmlWriter.writeElementString("QUERY_MODE", "1");
                } else {
                    xmlWriter.writeElementString("QUERY_MODE", queryMode);
                }
                xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                xmlWriter.writeElementString("QUERY_SN", p_reqQry.contractDetail.askNumber);
                xmlWriter.writeElementString("ACCOUNT_NO", p_reqQry.contractDetail.payAct);
                String agrType = "";
                if ("9108JFBAuth".equals(p_reqQry.reqHeader.commandCode)) {
                    agrType = "1";
                } else if ("9108JFBCntr".equals(p_reqQry.reqHeader.commandCode)) {
                    agrType = "2";
                }else{
                    agrType = "0";
                }
                xmlWriter.writeElementString("AGR_TYPE", agrType);

                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendJFBToBank(xmlWriter.toXmlString(), actItem, bankHeader.REQ_SN);

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/HEAD/RET_MSG");

                        String tmpRespCode = tmpBkReader.getFirstText("/AIPG/HEAD/RET_CODE");
                        if ("0000".equals(tmpRespCode)) {
                            String tmpRespInfo = tmpBkReader.getFirstText("/AIPG/BODY/QAGRRSP/ERR_MSG");
                            if (StringHelper.hasAnyChar(tmpRespInfo)) {
                                tmpRetDetail.respInfo = tmpRespInfo;
                            }

                            String contractState = tmpBkReader.getFirstText("/AIPG/BODY/QAGRRSP/STATUS");
                            if ("0".equals(contractState)) {
                                contractState = ContractState.SUCCESS;
                            } else if ("1".equals(contractState)) {
                                contractState = ContractState.FAIL;
                            } else {
                                contractState = ContractState.UNSIGNED;
                            }
                            tmpRetDetail.signState = contractState;

                            tmpRetDetail.authCode = tmpBkReader.getFirstText("/AIPG/BODY/QAGRRSP/AGRMNO");
                            tmpRetDetail.unifiedCode = getBankConfig().getMapValueByKey("contractMapping", tmpRespCode);
                        } else if ("1002".equals(tmpRespCode)) {
                            tmpRetDetail.respCode = "0";
                            tmpRetDetail.signState = ContractState.UNSIGNED;
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/HEAD/RET_MSG");
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/AIPG/HEAD/RET_MSG");
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "未找到账号:[" + p_reqQry.contractDetail.recAct + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }
        return tmpRetDetail;
    }
}